/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sle_announce_hal.h"
#include "sle_loader_hal.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

static SleAnnounceHdiOpts* g_sleAnnounceHalOpts = NULL;
static SleAnnounceHdiCallbacks* g_sleAnnounceHdiCbs = NULL;
static SleAnnounceHalCallbacks* g_sleAnnounceHalCbs = NULL;

static void OnSleHdiStartAnnounceCallback(uint32_t announceId, SleHdiErrorCode errCode)
{
    SLE_LOGI("OnSleHdiStartAnnounceCallback announceId = %{public}d, errCode(0x%{public}08X)", announceId, errCode);
    if (g_sleAnnounceHalCbs != NULL && g_sleAnnounceHalCbs->OnAnnounceHalStartAnnounceCb != NULL) {
        g_sleAnnounceHalCbs->OnAnnounceHalStartAnnounceCb(announceId, SleHalGetErrorCode(errCode));
    }
}

static void OnSleHdiStopAnnounceCallback(uint32_t announceId, SleHdiErrorCode errCode)
{
    SLE_LOGI("OnSleHdiStopAnnounceCallback announceId = %{public}d, errCode(0x%{public}08X)", announceId, errCode);
    if (g_sleAnnounceHalCbs != NULL && g_sleAnnounceHalCbs->OnAnnounceHalStopAnnounceCb != NULL) {
        g_sleAnnounceHalCbs->OnAnnounceHalStopAnnounceCb(announceId, SleHalGetErrorCode(errCode));
    }
}

static void OnSleHdiTerminalAnnounceCallback(uint32_t announceId)
{
    SLE_LOGD("OnSleHdiTerminalAnnounceCallback announceId = (%{public}d", announceId);
    if (g_sleAnnounceHalCbs != NULL && g_sleAnnounceHalCbs->OnAnnounceHalTerminalAnnounceCb != NULL) {
        g_sleAnnounceHalCbs->OnAnnounceHalTerminalAnnounceCb(announceId);
    }
}

static void OnSleHdiRemoveAnnounceCallback(uint32_t announceId, SleHdiErrorCode errCode)
{
    SLE_LOGD("OnSleHdiRemoveAnnounceCallback announceId = %{public}d, errCode(0x%{public}08X)", announceId, errCode);
    if (g_sleAnnounceHalCbs != NULL && g_sleAnnounceHalCbs->OnAnnounceHalRemoveAnnounceCb != NULL) {
        g_sleAnnounceHalCbs->OnAnnounceHalRemoveAnnounceCb(announceId, errCode);
    }
}

SleHalErrorCode InitSleAnnounceHal(void)
{
    SLE_LOGI("InitSleAnnounceHal");
    SLE_ASSERT_AND_RETURN_RET_LOG(g_sleAnnounceHalOpts == NULL, SLE_HAL_SUCCESS, "sleAnnounceHal has been Inited");
    SleHalErrorCode ret = SLE_HAL_ERR_UNKNOWN;
    g_sleAnnounceHalOpts = (SleAnnounceHdiOpts*)malloc(sizeof(SleAnnounceHdiOpts));
    ret = GetSleAnnounceHalOpts(g_sleAnnounceHalOpts);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "GetSleAnnounceHalOpts fail(%{public}d)", ret);
    SLE_ASSERT_AND_RETURN_RET(g_sleAnnounceHalOpts != NULL, SLE_HAL_ERR_COMMON);
    if(g_sleAnnounceHdiCbs == NULL) {
        g_sleAnnounceHdiCbs = (SleAnnounceHdiCallbacks*)malloc(sizeof(SleAnnounceHdiCallbacks));
        g_sleAnnounceHdiCbs->OnAnnounceStartCb = OnSleHdiStartAnnounceCallback;
        g_sleAnnounceHdiCbs->OnAnnounceStopCb = OnSleHdiStopAnnounceCallback;
        g_sleAnnounceHdiCbs->OnAnnounceTerminalCb = OnSleHdiTerminalAnnounceCallback;
        g_sleAnnounceHdiCbs->OnAnnounceRemoveCb = OnSleHdiRemoveAnnounceCallback;
        SLE_ASSERT_AND_RETURN_RET_LOG(g_sleAnnounceHdiCbs != NULL, SLE_HAL_ERR_DRIVER_OR_SYSTEM, "SleHal or SleDriver has not been inited");      
    }
    SleHdiErrorCode result = g_sleAnnounceHalOpts->registerAnnounceCbks(g_sleAnnounceHdiCbs);
    ret = SleHalGetErrorCode(result);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "registerAnnounceCbks fail(0x%{public}08X)", result);
    g_sleAnnounceHalCbs = (SleAnnounceHalCallbacks*)malloc(sizeof(SleAnnounceHalCallbacks));
    return ret;
}

SleHalErrorCode DeinitSleAnnounceHal(void)
{
    SLE_LOGI("DeinitSleAnnounceHal");
    SLE_ASSERT_AND_RETURN_RET_LOG(g_sleAnnounceHalOpts != NULL, SLE_HAL_SUCCESS, "sleAnnounceHal has not been Inited");
    free(g_sleAnnounceHalOpts);
    g_sleAnnounceHalOpts = NULL;
    free(g_sleAnnounceHdiCbs);
    g_sleAnnounceHdiCbs = NULL;
    free(g_sleAnnounceHalCbs);
    g_sleAnnounceHalCbs = NULL;
    return SLE_HAL_SUCCESS;
}

SleHalErrorCode SleAnnounceHalSetAnnounceData(uint8_t announceId, const SleAnnounceData *data)
{
    SLE_LOGD("SleAnnounceHalSetAnnounceData");
    SLE_ASSERT_AND_RETURN_RET(g_sleAnnounceHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(data != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SleHdiErrorCode result = g_sleAnnounceHalOpts->setAnnounceData(announceId, data);
    SleHalErrorCode ret = SleHalGetErrorCode(result);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "setAnnounceData fail(0x%{public}08X)", result);
    return ret;
}

SleHalErrorCode SleAnnounceHalSetAnnounceParam(uint8_t announceId, const SleAnnounceParam *announcHalParam)
{
    SLE_LOGI("SleAnnounceHalSetAnnounceParam announceId(%{public}d)", announceId);
    SLE_LOGD("\tmode(%hu) role(%hu) level(%hu) channel(%hu)",announcHalParam->mode, announcHalParam->role
        , announcHalParam->level, announcHalParam->channelMap);
    SLE_LOGD("\tinterval[(%{public}d:%{public}d]", announcHalParam->annonceIntervalMin, announcHalParam->annonceIntervalMax);
    SLE_ASSERT_AND_RETURN_RET(g_sleAnnounceHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(announcHalParam != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SleHdiErrorCode result = g_sleAnnounceHalOpts->setAnnounceParam(announceId, announcHalParam);
    SleHalErrorCode ret = SleHalGetErrorCode(result);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "setAnnounceParam fail(0x%{public}08X)", result);
    return ret;
}

SleHalErrorCode SleAnnounceHalStartAnnounce(uint8_t announceId)
{
    SLE_LOGI("SleAnnounceHalStartAnnounce announceId(%hu)", announceId);
    SLE_ASSERT_AND_RETURN_RET(g_sleAnnounceHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SleHdiErrorCode result = g_sleAnnounceHalOpts->startAnnounce(announceId);
    SleHalErrorCode ret = SleHalGetErrorCode(result);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "startAnnounce fail(0x%{public}08X)", result);
    return ret;
}

SleHalErrorCode SleAnnounceHalStopAnnounce(uint8_t announceId)
{
    SLE_LOGI("SleAnnounceHalStopAnnounce announceId(%hu)", announceId);
    SLE_ASSERT_AND_RETURN_RET(g_sleAnnounceHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SleHdiErrorCode result = g_sleAnnounceHalOpts->stopAnnounce(announceId);
    SleHalErrorCode ret = SleHalGetErrorCode(result);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "stopAnnounce fail(0x%{public}08X)", result);
    return ret;
}

SleHalErrorCode SleAnnounceHalRegisterCallbacks(const SleAnnounceHalCallbacks *callback)
{
    SLE_LOGI("SleAnnounceHalRegisterCallbacks");
    SLE_ASSERT_AND_RETURN_RET(g_sleAnnounceHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(callback != NULL, SLE_HAL_ERR_INVALID_PARAM);
    memcpy(g_sleAnnounceHalCbs, callback, sizeof(SleAnnounceHalCallbacks));
    return SLE_HAL_SUCCESS;
}


